import { http } from "@/utils/http";
import type { ApiResponse } from "../../user";
import { ensureArray, normalisePagination, toNumber } from "@/api/_helpers";

const RECORD_BASE = "/system/notify/record";

export interface NotifyRecipientItem {
  id: number;
  message_id: number;
  target_type: string;
  target_id: string | number;
  channel: string;
  status: number;
  status_text?: string;
  send_attempts: number;
  read_time?: string;
  sent_at?: string;
  create_time?: string;
  update_time?: string;
  [key: string]: any;
}

export interface NotifyRecordItem {
  id: number;
  template_id: number;
  template_type: string;
  template_name?: string;
  category?: string;
  title: string;
  content: string;
  payload: Record<string, any>;
  status: number;
  status_text?: string;
  sent_at?: string;
  create_time?: string;
  update_time?: string;
  recipients: NotifyRecipientItem[];
  [key: string]: any;
}

export interface NotifyRecordListParams {
  page?: number;
  page_size?: number;
  keyword?: string;
  status?: number | string;
  channel?: string;
  template_id?: number | string;
  template_type?: string;
  category?: string;
  date_start?: string;
  date_end?: string;
}

export interface NotifyRecordListResult {
  list: NotifyRecordItem[];
  total: number;
  pageSize: number;
  currentPage: number;
  templates: Array<{ id: number; name: string; type: string }>;
  channels: string[];
  statuses: Array<{ label: string; value: number | string }>;
  raw?: any;
}

export interface ResendPayload {
  recipient_ids?: number[];
}

export interface MarkReadPayload {
  recipient_id?: number;
  target_type?: string;
  target_id?: number | string;
}

export interface CreateRecipientPayload {
  target_type: string;
  target_id: number | string;
  channel: string;
}

export interface CreateRecordPayload {
  template_id?: number | null;
  template_type?: string;
  title?: string;
  content?: string;
  data?: Record<string, any> | null;
  payload?: Record<string, any> | null;
  recipients: Array<CreateRecipientPayload>;
  route?: string;
}

const parsePayload = (value: unknown): Record<string, any> => {
  if (!value) return {};
  if (typeof value === "string") {
    try {
      const parsed = JSON.parse(value);
      if (typeof parsed === "object" && parsed !== null) {
        return parsed as Record<string, any>;
      }
      return { value: parsed };
    } catch {
      return { raw: value };
    }
  }
  if (typeof value === "object") {
    return { ...(value as Record<string, any>) };
  }
  return { value };
};

const mapRecipient = (item: Record<string, any>): NotifyRecipientItem => ({
  id: toNumber(item.id, 0),
  message_id: toNumber(item.message_id ?? item.notify_message_id, 0),
  target_type: item.target_type ?? "",
  target_id: item.target_id ?? item.target ?? "",
  channel: item.channel ?? item.notify_channel ?? "",
  status: toNumber(item.status ?? item.state ?? 0, 0),
  status_text: item.status_text ?? item.status_label ?? item.state_label ?? "",
  send_attempts: toNumber(item.send_attempts ?? item.retry_count, 0),
  read_time: item.read_time ?? item.read_at ?? "",
  sent_at: item.sent_at ?? item.send_time ?? "",
  create_time: item.create_time ?? item.created_at ?? "",
  update_time: item.update_time ?? item.updated_at ?? ""
});

const mapRecord = (item: Record<string, any>): NotifyRecordItem => ({
  id: toNumber(item.id, 0),
  template_id: toNumber(
    item.template_id ?? item.notify_template_id ?? item.template?.id,
    0
  ),
  template_type:
    item.template_type ?? item.template?.type ?? item.type ?? "unknown",
  template_name: item.template_name ?? item.template?.name ?? "",
  category: item.category ?? item.template?.category ?? "",
  title: item.title ?? "",
  content: item.content ?? "",
  payload: parsePayload(item.payload),
  status: toNumber(item.status ?? item.message_status ?? 0, 0),
  status_text:
    item.status_text ?? item.status_label ?? item.message_status_text ?? "",
  sent_at: item.sent_at ?? item.send_time ?? "",
  create_time: item.create_time ?? item.created_at ?? "",
  update_time: item.update_time ?? item.updated_at ?? "",
  recipients: ensureArray<Record<string, any>>(
    item.recipients ?? item.targets ?? []
  ).map(mapRecipient)
});

const fetchList = async (
  params: NotifyRecordListParams = {}
): Promise<NotifyRecordListResult> => {
  const page = toNumber(params.page, 1);
  const pageSize = toNumber(params.page_size, 10);

  const res = await http.request<ApiResponse<any>>("get", RECORD_BASE, {
    params: {
      ...params,
      page,
      page_size: pageSize
    }
  });

  const payload = (res?.data as Record<string, any>) ?? {};
  const listSource =
    payload.list ?? payload.data ?? payload.records ?? payload.items ?? [];
  const list = ensureArray<Record<string, any>>(listSource).map(mapRecord);

  const pagination = normalisePagination(
    payload.pagination ?? payload,
    page,
    pageSize,
    list.length
  );

  const templates = ensureArray<any>(
    payload.templates ?? payload.template ?? []
  )
    .map((item: any) => ({
      id: toNumber(item.id ?? item.template_id, 0),
      name: item.name ?? item.title ?? "",
      type: item.type ?? ""
    }))
    .filter(item => item.id > 0 || item.type);

  const channels = ensureArray<string>(
    payload.channels ?? payload.channel_options ?? []
  );

  const statuses = ensureArray<any>(
    payload.statuses ?? payload.status_options ?? []
  )
    .map((item: any) => {
      if (typeof item === "string" || typeof item === "number") {
        return { label: String(item), value: item };
      }
      return {
        label: item.label ?? item.name ?? "",
        value: item.value ?? item.code ?? ""
      };
    })
    .filter(option => option.label !== "");

  return {
    list,
    total: pagination.total,
    pageSize: pagination.pageSize,
    currentPage: pagination.currentPage,
    templates,
    channels,
    statuses,
    raw: payload
  };
};

const fetchDetail = async (id: number): Promise<NotifyRecordItem> => {
  const res = await http.request<ApiResponse<any>>(
    "get",
    `${RECORD_BASE}/${id}`
  );
  const payload = (res?.data as Record<string, any>) ?? {};
  return mapRecord(payload ?? {});
};

const resend = async (
  id: number,
  payload: ResendPayload = {}
): Promise<boolean> => {
  const res = await http.request<ApiResponse<any>>(
    "post",
    `${RECORD_BASE}/${id}/resend`,
    {
      data: payload
    }
  );
  if (typeof res?.data === "boolean") return res.data;
  if (res?.success !== undefined) return Boolean(res.success);
  return true;
};

const remove = async (id: number): Promise<boolean> => {
  const res = await http.request<ApiResponse<any>>(
    "delete",
    `${RECORD_BASE}/${id}`
  );
  if (typeof res?.data === "boolean") return res.data;
  if (res?.success !== undefined) return Boolean(res.success);
  return true;
};

const create = async (
  payload: CreateRecordPayload
): Promise<NotifyRecordItem> => {
  const res = await http.request<ApiResponse<any>>(
    "post",
    "/system/notify/message",
    {
      data: payload
    }
  );
  const data = (res?.data as Record<string, any>) ?? {};
  return mapRecord(data);
};

const markRead = async (
  id: number,
  payload: MarkReadPayload = {}
): Promise<NotifyRecipientItem> => {
  const res = await http.request<ApiResponse<any>>(
    "post",
    `${RECORD_BASE}/${id}/read`,
    {
      data: payload
    }
  );
  const data = (res?.data as Record<string, any>) ?? {};
  return mapRecipient(data);
};

export default {
  fetchList,
  fetchDetail,
  resend,
  remove,
  create,
  markRead
};
